/**
 * \file impression.c
 *\author H4201
 */

#include <signal.h>
#include <mqueue.h>

#include "impression.h"
#include "ResChaineCond.h"
#include "../interface/partage_simu.h"
#include "../interface/messqueue.h"
#include "../interface/mutexpartage.h"
#include "../interface/variablesglobales.h"
#include "../utils/utils.h"

/*MODULES USED*/
#include <errno.h>

/*PROTOTYPES OF LOCAL FUNCTIONS*/
void init_impression();
void detruire_impression();

/*GLOBAL VARIABLES*/
/**
boite au lettre dans laquelle le thread lit l'arrivée des cartons
*/
static mqd_t bal_carton;
/**
boite au lettre dans laquelle le thread envoi les cartons une fois l'impression effectuée
*/
static mqd_t bal_impression;
/**
boite au lettre du log
*/
static mqd_t bal_messages;
/**
boite au lettre dans laquelle le thread envois les erreurs qu'il rencontre
*/
static mqd_t bal_erreurs;

/**.
Condition sur la boucle infinie du thread. Ne change jamais.
*/
static unsigned short continuer = 1;

/*EXPORTED FUNCTIONS*/
/**
	* thread simulant l'impression sur les cartons.
	* Il lis dans la boite au lettre BAL_CARTON_NAME et traite les messages 
	*\param parameter parametre inutilsé
	*\return 0 quand le thread se termine correctement
*/
void* impression(void *parameter) {
	// non utilisé
	(void) parameter;
	
	// === init ===
	init_impression();

	// === moteur ===
	while (continuer) {
		struct message msg_recu;
		struct message msg_envoi;
		struct mq_attr attr;

		if (lire_message(bal_carton, &msg_recu) == -1) {
			perror("[Impression] Echec lire_message");
			exit(1);
		}

		if(msg_recu.type == ARRET) {
			break;
		}

		//problème capteur d'imprimante
		while (g_shm->imp == NOK) {
			printf("[Impression] probleme imprimante\n");
			struct message msg_err_imp;
			msg_err_imp.type = ERRIMPR;

			mq_send (bal_erreurs, (char *)&msg_err_imp, sizeof(struct message), 1); 

			sem_wait(&sem_err_imprim);			
		}

		//envoyer message d'erreur bal pleine
		mq_getattr(bal_impression, &attr);
		if (attr.mq_curmsgs == attr.mq_maxmsg) { 
			printf("[Impression] erreur BM impression pleine\n"); 
			struct message msg_err_boite_pleine;
			msg_err_boite_pleine.type = ERRFILE;
			mq_send (bal_erreurs, (char *)&msg_err_boite_pleine, sizeof(struct message), 1); 
		}

		// === supposément impression ici
		printf("[Impression] impression\n");
		msg_envoi.type = EMPALETTER;
		msg_envoi.params[0] = msg_recu.params[0];
		msg_envoi.params[1] = msg_recu.params[1];
		msg_envoi.params[2] = msg_recu.params[4];
		mq_send (bal_impression, (char *)&msg_envoi, sizeof(struct message), 1); 
		mq_send (bal_messages, (char *)&msg_envoi, sizeof(struct message), 1); 

	}

	// === destruction
	detruire_impression();

	return 0;
}

/*LOCAL FUNCTIONS*/
/**
	* initialise les message queue du thread.
*/
void init_impression() {
	bal_carton = ouvrir_mqueue(BAL_CARTONS_NAME, O_RDONLY);
	bal_impression = ouvrir_mqueue(BAL_IMPRESSION_NAME, O_WRONLY);
	bal_messages = ouvrir_mqueue(BAL_MESSAGES_NAME, O_WRONLY);
	bal_erreurs = ouvrir_mqueue(BAL_ERREURS_NAME, O_WRONLY);
}

/**
	* libère les messages queue et transfère le message d'arrey
*/
void detruire_impression() {
	printf("[Impression] destruction\n");
	//envoi du message de fin de prod à la mise en palette
	struct message msg;
	msg.type = ARRET;
	mq_send (bal_impression, (char *)&msg, sizeof(struct message), 1); //1 is priority

	mq_close(bal_carton);
	mq_close(bal_impression);
	mq_close(bal_messages);
	mq_close(bal_erreurs);

	pthread_exit(0);
}

/**
	* supprime tous les messages de la boite au lettres bal_carton
*/
void vider_bal_cartons() {
	vider_bal(bal_carton);
}
